﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Web;

namespace Outlook.WorkItems.Extension.Manager.TeamPortal
{
    /// <summary>
    /// Manage Upload to Sharepoint Libraries document
    /// </summary>
    public static class DocLibHelper
    {
        static string EncodeMetaInfo(Dictionary<string, object> metaInfo)
        {
            if (metaInfo == null)
                return "";
            var sb = new StringBuilder();
            foreach (KeyValuePair<string, object> kvp in metaInfo)
            {
                if (kvp.Value == null) 
                    continue;

                var fieldName = kvp.Key;

                switch (fieldName)
                {
                    case "Title":
                        fieldName = "vti_title";
                        break;
                }
                var data = EscapeVectorChars(kvp.Value.ToString());
                var dataTypeCode = "S";
                switch (kvp.Value.GetType().FullName)
                {
                    case "System.Boolean":
                        dataTypeCode = "B";
                        break;
                    case "System.DateTime":
                        data = ((DateTime)kvp.Value).ToString("s") + "Z";
                        break;
                }
                sb.AppendFormat("{0};{1}W|{2};", fieldName, dataTypeCode, data);
            }
            return HttpUtility.UrlEncode(sb.ToString().TrimEnd(';'));
        }
        static string EscapeVectorChars(string value)
        {
            var sb = new StringBuilder();
            foreach (var c in value)
            {
                switch (c)
                {
                    case ';':
                    case '|':
                    case '[':
                    case ']':
                    case '\\':
                        sb.Append("\\");
                        break;
                }
                sb.Append(c);
            }
            return sb.ToString();
        }
        public static string GetWebUrl(string url)
        {
            try
            {
                url = url.Substring(0, url.LastIndexOf("/"));
                try
                {
                    using (var webClient = new WebClient())
                    {
                        webClient.Credentials = CredentialCache.DefaultCredentials;
                        webClient.Headers.Add("Content-Type", "application/x-vermeer-urlencoded");
                        webClient.Headers.Add("X-Vermeer-Content-Type", "application/x-vermeer-urlencoded");
                        byte[] data = Encoding.UTF8.GetBytes("method=open+service%3a12.0.4518.1016&service_name=%2f");
                        var result = Encoding.UTF8.GetString(webClient.UploadData(url + "/_vti_bin/_vti_aut/author.dll", "POST", data));
                        if (result.IndexOf("\n<li>status=327684") == -1)
                            return url;
                        throw new Exception();
                    }
                }
                catch
                {
                    return GetWebUrl(url);
                }
            }
            catch
            {
                return null;
            }
        }
        public static bool Upload(string destinationUrl, byte[] bytes, Dictionary<string, object> metaInfo)
        {
            string result;
            var webUrl = GetWebUrl(destinationUrl);
            var documentName = destinationUrl.Substring(webUrl.Length + 1);
            return Upload(webUrl, documentName, bytes, metaInfo, out result);
        }
        public static bool Upload(string webUrl, string documentName, byte[] bytes, Dictionary<string, object> metaInfo, out string result)
        {
            var putOption = "overwrite,createdir,migrationsemantics";
            // see http://msdn2.microsoft.com/en-us/library/ms455325.aspx        
            string comment = null;
            var keepCheckedOut = false;
            var method = "method=put+document%3a12.0.4518.1016&service_name=%2f&document=[document_name={0};meta_info=[{1}]]&put_option={2}&comment={3}&keep_checked_out={4}\n";
            method = String.Format(method, documentName, EncodeMetaInfo(metaInfo), putOption, HttpUtility.UrlEncode(comment), keepCheckedOut.ToString().ToLower());
            var data = new List<byte>();
            data.AddRange(Encoding.UTF8.GetBytes(method));
            data.AddRange(bytes);
            try
            {
                using (var webClient = new WebClient())
                {
                    webClient.Credentials = CredentialCache.DefaultCredentials;
                    webClient.Headers.Add("Content-Type", "application/x-vermeer-urlencoded");
                    webClient.Headers.Add("X-Vermeer-Content-Type", "application/x-vermeer-urlencoded");
                    result = Encoding.UTF8.GetString(webClient.UploadData(webUrl + "/_vti_bin/_vti_aut/author.dll", "POST", data.ToArray()));
                    if (result.IndexOf("\n<p>message=successfully") < 0)
                        throw new Exception(result);
                }
            }
            catch (Exception ex)
            {
                result = ex.Message;
                return false;
            }
            return true;
        }
    }
}
